package com.funmi.lizip.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.funmi.lizip.entity.Battery;
import com.funmi.lizip.entity.Patrol;
import com.funmi.lizip.entity.PatrolTrack;
import com.funmi.lizip.entity.SolarDevice;
import com.funmi.lizip.entity.dto.patrolTrack.TrackMsg;
import com.funmi.lizip.mapper.PatrolTrackMapper;
import com.funmi.lizip.service.BatteryService;
import com.funmi.lizip.service.PatrolService;
import com.funmi.lizip.service.SolarDeviceService;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.sql.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.funmi.lizip.utils.CaculateDistanceTest.getDistanceMeter;

@Component
public class PatrolUtil {
    @Autowired
    private PatrolTrackMapper patrolTrackMapper;
    @Autowired
    private PatrolService patrolService;
    @Autowired
    private BatteryService batteryService;
    @Autowired
    private SolarDeviceService solarDeviceService;

    private static GlobalCoordinates source;
    private static GlobalCoordinates target;
    private Double distance = 0.0;
    private static int start = 0;
    private static int end = 0;
    private static int point = 0;

    /**
     * 定时查看是否存在超过一天未结束的巡护任务
     */
    @Scheduled(cron = "0 0/10 * * * ? ")
    public void autoEnd() {
        QueryWrapper<PatrolTrack> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        queryWrapper.between("gmt_modified", (LocalDateTime.of(2019, 10, 12, 6, 30)), LocalDateTime.now().minusDays(1));

        // 监控轨迹24小时没有更新轨迹，且未结束的任务。
        List<PatrolTrack> patrolTracks = patrolTrackMapper.selectList(queryWrapper);
        if (patrolTracks.size() <= 0 || ObjectUtils.isEmpty(patrolTracks.get(0))) {
            return;
        }

        patrolTracks.forEach(patrolTrack -> {
            LocalDateTime localDateTime = LocalDateTime.now().minusDays(1);
            patrolTrack.setPatrolDate(localDateTime);
            patrolTrack.setStatus(false);
            if (!ObjectUtils.isEmpty(patrolTrack.getTrackMsg())){
                // 获取轨迹详情
                JSONArray trackMsg = patrolTrack.getTrackMsg();
                String s = trackMsg.toString();
                List<TrackMsg> trackMsgs = JSONArray.parseArray(s, TrackMsg.class);
                // 排序
                List<TrackMsg> collect = trackMsgs.stream().sorted(Comparator.comparing(TrackMsg::getCreateTime)).collect(Collectors.toList());
                // 计算距离
                for (int i = 0; i < collect.size() - 1; i++) {
                    List<Double> doubles = JSONArray.parseArray(collect.get(0).getLocation().toString(), Double.class);
                    source = new GlobalCoordinates(doubles.get(0), doubles.get(1));
                    List<Double> doubles2 = JSONArray.parseArray(collect.get(1).getLocation().toString(), Double.class);
                    target = new GlobalCoordinates(doubles2.get(0), doubles.get(1));

                    double meter1 = getDistanceMeter(source, target, Ellipsoid.Sphere);
                    distance += meter1;
                }

                distance = (double) (distance.floatValue() / 1000);
                patrolTrack.setDistance(distance);
            }

            int j = patrolTrackMapper.updateById(patrolTrack);

            // 相关巡护任务是否结束
            Patrol byId = patrolService.getById(patrolTracks.get(0).getPatrolId());
            byId.setEndTime(localDateTime);
            byId.setStatus(2);
            patrolService.updateById(byId);
        });

    }

    /**
     * 定时 获取网页上的设备电池数据
     */
    @Scheduled(cron = "0 0/5 * * * ? ")
    @Transactional(rollbackFor = Exception.class)
    public void getBattery() {
        String url = "http://222.213.242.34:8001/#/";
        ChromeOptions chromeOptions = new ChromeOptions();
        System.setProperty("webdriver.chrome.driver", "D:\\Python3.11\\chromedriver.exe");
        chromeOptions.addArguments("--headless");
        WebDriver webDriver = new ChromeDriver(chromeOptions);
        webDriver.get(url);
        try {
            Actions actions = new Actions(webDriver);
            List<WebElement> elements = webDriver.findElements(By.className("__item"));
            Actions click = actions.click(elements.get(2));
            click.perform();
            Actions click1 = actions.click(elements.get(2));
            click1.perform();
            WebElement webElement = webDriver.findElement(By.className("vxe-table--render-wrapper"));
            //获取页面全部信息
            String text = webElement.getText();

            String substring = text.substring(text.indexOf("1"));
            String[] split = substring.split("");
            // 转化成 为字符串集合
            List<String> strings1 = get(substring);
            // 添加最后一位电池情况, 更改则需要改。
            if (split[substring.length()-1].matches("[\u4e00-\u9fa5]")){
                strings1.add(substring.substring(683-2));
            }

            // 置入Battery对象中
            List<Battery>  batteryList = batteryBeanUtil(strings1);
            batteryList.forEach(battery -> {
                QueryWrapper<Battery> batteryQueryWrapper = new QueryWrapper<>();
                batteryQueryWrapper.eq("site", battery.getSite());
                Battery one = batteryService.getOne(batteryQueryWrapper);
                if (!ObjectUtils.isEmpty(one)){
                    battery.setId(one.getId());
                    boolean b = batteryService.updateById(battery);
                }
            });
            start = 0;
            point = 0;
            end = 0;

        }finally {
            webDriver.close();
            //必须关闭资源
        }


    }

    @Scheduled(cron = "0 0/5 * * * ? ")
    @Transactional(rollbackFor = Exception.class)
    public void getSolarDevice() throws Exception {
        String mdbPath = "D:\\YNMonitor\\MonitorMain.mdb";
        String mdbSql = "SELECT * FROM solar_device";
        List<SolarDevice> list = PatrolUtil.resolverSolarDevice(mdbPath, mdbSql);
        list.forEach(solarDevice -> solarDeviceService.saveOrUpdate(solarDevice));
    }

    /**
     * @param mdbPath mdb文件路径
     * @param mdbSql mdb执行sql
     * @return
     * @throws Exception
     */
    private static List<SolarDevice> resolverSolarDevice(String mdbPath, String mdbSql) throws Exception {
        if (mdbPath.isEmpty() || mdbSql.isEmpty()) {
            throw new Exception("mdb文件路径不能为空或者SQL语句不能为空或者返回字段列表不能为空");
        }
        List<SolarDevice> mdbEntityList = new ArrayList<>();
        Properties prop = new Properties();
        //设置编码
        prop.put("charSet", "UTF-8");
        //数据地址
        String dbUrl = "jdbc:ucanaccess://" + mdbPath;
        //引入驱动
        Class.forName("net.ucanaccess.jdbc.UcanaccessDriver").newInstance();
        try {
            //连接数据库资源
            Connection conn = DriverManager.getConnection(dbUrl, prop);
            //建立查询事务
            Statement statement = conn.createStatement();
            //执行查询
            ResultSet result = statement.executeQuery(mdbSql);

            ResultSetMetaData metaData = result.getMetaData();

            int count = metaData.getColumnCount();
            List<String> mdbColumnList = new ArrayList<>(count);
            //动态解析字段名
            for (int i = 1; i <= count; i++) {
                mdbColumnList.add(metaData.getColumnName(i));
            }
            //解析执行结果
            Map<String, Object> mdbMapList = new HashMap<>(16);
            while (result.next()) {
                for (String col : mdbColumnList) {
                    mdbMapList.put(col, result.getObject(col));
                }
                SolarDevice mdb = JSONObject.parseObject(JSONObject.toJSONString(mdbMapList), SolarDevice.class);
                mdbEntityList.add(mdb);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回数据
        return mdbEntityList;
    }

    /**
     * 将 字符串对象 转换 为 Battery对象
     * @param strings
     * @return
     */
    public List<Battery> batteryBeanUtil(List<String> strings) {
        ArrayList<Battery> batteryList = new ArrayList<>();

        for (String s : strings) {
            //String trim = s.trim();
            Battery battery = new Battery();
            String[] split = s.split("\n");
            if (split.length < 10){
                continue;
            }
            if (split[1].substring(0, 1).matches("[\u4e00-\u9fa5]")) {
                battery.setSite(split[1]);
                battery.setVoltage(split[2]);
                battery.setCurrent(split[3]);
                battery.setSoc(split[4]);
                battery.setBatteryStatus(split[5]);
                battery.setChargingDeviceStatus(split[6]);
                battery.setDischargeEquipmentStatus(split[7]);
                battery.setHighest(split[8]);
                battery.setLowest(split[9]);
                batteryList.add(battery);
            }else {
                // System.out.println(split[1]);
                // System.out.println(split[0]);
                battery.setSite(split[2]);
                battery.setVoltage(split[3]);
                battery.setCurrent(split[4]);
                battery.setSoc(split[5]);
                battery.setBatteryStatus(split[6]);
                battery.setChargingDeviceStatus(split[7]);
                battery.setDischargeEquipmentStatus(split[8]);
                battery.setHighest(split[9]);
                battery.setLowest(split[10]);
                batteryList.add(battery);
            }
            // System.out.println(split.length);
        }
        return batteryList;
    }

    /**
     * 爬取到的数据 硬解 拆分成为字符串集合
     * @param substring
     * @return
     */
    public List<String> get(String substring) {
        String[] split = substring.split("");
        List<String> strings = new ArrayList<>(Arrays.asList(split));

        ArrayList<String> list = new ArrayList<>();
        while ((end + 16) <= strings.size()){
            for (int i = end; i < strings.size(); i++) {
                if (strings.get(i).matches("[\u4e00-\u9fa5]")){
                    start = i;
                    break;
                }
            }
            for (int i = start; i < strings.size(); i++) {
                if (!strings.get(i).matches("[\u4e00-\u9fa5]")){
                    point = i;
                    break;
                }
            }
            for (int i = point; i < strings.size(); i++) {
                if (strings.get(i).matches("[\u4e00-\u9fa5]")){
                    end =i;
                    break;
                }
            }
            if ((end - start) < 7){
                for (int i = end; i < strings.size(); i++) {
                    if (!strings.get(i).matches("[\u4e00-\u9fa5]")){
                        point = i;
                        break;
                    }
                }
                for (int i = point; i < strings.size(); i++) {
                    if (strings.get(i).matches("[\u4e00-\u9fa5]")){
                        end =i;
                        break;
                    }
                }
            }
            if (list.size() == 0){
                list.add(substring.substring(0, end-1));
                continue;
            }
            if (list.size() < 8){
                list.add(substring.substring(start-1, end-2));
                continue;
            }
            if (list.size() == 8){
                list.add(substring.substring(start-2, end-4));
                continue;
            }
            list.add(substring.substring(start-4, end-4));
        }

        return list;
    }

}
